package cn.zurish.cloud.work.service;

import cn.zurish.cloud.work.dao.entity.Temperature;
import cn.zurish.cloud.work.dao.entity.WorkTimes;
import cn.zurish.cloud.work.dao.mapper.TemperatureMapper;
import cn.zurish.cloud.work.dao.mapper.WorkTimesMapper;
import cn.zurish.cloud.work.modbus.MCGSProModbusReader;
import cn.zurish.cloud.work.modbus.MCGSProTemperatureReader;
import cn.zurish.cloud.work.modbus.WorkstationRuntimeReader;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

@Service
@RequiredArgsConstructor
public class ModbusDataService {


    private final TemperatureMapper temperatureMapper;


    private final WorkTimesMapper workTimesMapper;
    

    private  final Executor modbusTaskExecutor;

    // IP地址范围
    private static final String IP_PREFIX = "10.200.133.";
    private static final int IP_START = 1;
    private static final int IP_END = 253;

    /**
     * 每天早上7:30执行工位运行时间数据读取任务
     */
    @Scheduled(cron = "0 30 7 * * ?")
    public void readAndSaveWorkTimesDataMorning() {
        System.out.println("开始执行早上工位运行时间数据读取任务...");
        readAndSaveWorkTimesData();
        System.out.println("早上工位运行时间数据读取任务执行完成。");
    }

    /**
     * 每天晚上7:30执行工位运行时间数据读取任务
     */
    @Scheduled(cron = "0 30 19 * * ?")
    public void readAndSaveWorkTimesDataEvening() {
        System.out.println("开始执行晚上工位运行时间数据读取任务...");
        readAndSaveWorkTimesData();
        System.out.println("晚上工位运行时间数据读取任务执行完成。");
    }

    /**
     * 每30分钟执行一次温度数据读取任务
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    public void readAndSaveTemperatureDataPeriodically() {
        System.out.println("开始执行温度数据读取任务...");
        readAndSaveTemperatureData();
        System.out.println("温度数据读取任务执行完成。");
    }

    /**
     * 读取工位运行时间数据并存储到数据库
     */
    private void readAndSaveWorkTimesData() {
        List<CompletableFuture<WorkTimes>> futures = new ArrayList<>();
        List<WorkTimes> workTimesList = new ArrayList<>();
        int successCount = 0;
        
        // 遍历IP地址范围
        for (int i = IP_START; i <= IP_END; i++) {
            String ip = IP_PREFIX + i;
            
            // 检查IP是否可达
            if (!isIpReachable(ip)) {
                continue;
            }
            
            // 异步处理每个设备
            CompletableFuture<WorkTimes> future = CompletableFuture.supplyAsync(() -> {
                try {
                    // 读取设备编号
                    String leftMachineCode = MCGSProModbusReader.readAsciiString(ip, 2624, 16);
                    String rightMachineCode = MCGSProModbusReader.readAsciiString(ip, 2689, 16);

                    // 读取工位运行时间数据
                    float leftHour = WorkstationRuntimeReader.readFloatValue(ip, 168);
                    float leftMinute = WorkstationRuntimeReader.readFloatValue(ip, 170);
                    float rightHour = WorkstationRuntimeReader.readFloatValue(ip, 172);
                    float rightMinute = WorkstationRuntimeReader.readFloatValue(ip, 174);

                    // 创建WorkTimes实体
                    WorkTimes workTimes = WorkTimes.builder()
                            .ipAddress(ip)
                            .leftMachineCode(leftMachineCode)
                            .rightMachineCode(rightMachineCode)
                            .leftRunHourTime((int) leftHour)
                            .leftRunMinutesTime((int) leftMinute)
                            .rightRunHourTime((int) rightHour)
                            .rightRunMinutesTime((int) rightMinute)
                            .createTime(new Date())
                            .build();
                    
                    // 打印成功读取的设备参数日志
                    System.out.println("成功读取工位运行时间数据 - IP: " + ip + 
                        ", 左工位编号: " + leftMachineCode + 
                        ", 右工位编号: " + rightMachineCode + 
                        ", 左工位小时: " + leftHour + 
                        ", 左工位分钟: " + leftMinute + 
                        ", 右工位小时: " + rightHour + 
                        ", 右工位分钟: " + rightMinute);
                    
                    return workTimes;
                } catch (Exception e) {
                    // 记录单个设备读取失败，继续处理其他设备
                    System.err.println("读取设备 " + ip + " 工位运行时间数据失败: " + e.getMessage());
                    return null;
                }
            }, modbusTaskExecutor);
            
            futures.add(future);
        }
        
        // 收集所有异步任务的结果
        for (CompletableFuture<WorkTimes> future : futures) {
            try {
                WorkTimes workTimes = future.get();
                if (workTimes != null) {
                    workTimesList.add(workTimes);
                    successCount++;
                }
            } catch (InterruptedException | ExecutionException e) {
                System.err.println("获取异步任务结果失败: " + e.getMessage());
            }
        }
        
        // 批量插入到数据库
        if (!workTimesList.isEmpty()) {
            workTimesMapper.insertBatchSomeColumn(workTimesList);
            System.out.println("成功插入 " + workTimesList.size() + " 条工位运行时间数据记录。");
        }
        
        System.out.println("工位运行时间数据读取任务完成，成功读取 " + successCount + " 台设备。");
    }

    /**
     * 读取温度数据并存储到数据库
     */
    private void readAndSaveTemperatureData() {
        List<CompletableFuture<Temperature>> futures = new ArrayList<>();
        List<Temperature> temperatureList = new ArrayList<>();
        int successCount = 0;
        
        // 遍历IP地址范围
        for (int i = IP_START; i <= IP_END; i++) {
            String ip = IP_PREFIX + i;
            
            // 检查IP是否可达
            if (!isIpReachable(ip)) {
                continue;
            }
            
            // 异步处理每个设备
            CompletableFuture<Temperature> future = CompletableFuture.supplyAsync(() -> {
                try {
                    // 读取设备编号
                    String leftMachineCode = MCGSProModbusReader.readAsciiString(ip, 2624, 16);
                    String rightMachineCode = MCGSProModbusReader.readAsciiString(ip, 2689, 16);

                    // 读取温度数据
                    float leftTopTemp = MCGSProTemperatureReader.readFloatValue(ip, 112);
                    float leftBottomTemp = MCGSProTemperatureReader.readFloatValue(ip, 114);
                    float rightTopTemp = MCGSProTemperatureReader.readFloatValue(ip, 116);
                    float rightBottomTemp = MCGSProTemperatureReader.readFloatValue(ip, 118);

                    // 创建Temperature实体
                    Temperature temperature = Temperature.builder()
                            .ipAddress(ip)
                            .leftMachineCode(leftMachineCode)
                            .rightMachineCode(rightMachineCode)
                            .leftTopTemp(leftTopTemp)
                            .leftBottomTemp(leftBottomTemp)
                            .rightTopTemp(rightTopTemp)
                            .rightBottomTemp(rightBottomTemp)
                            .createTime(new Date())
                            .build();
                    
                    // 打印成功读取的设备参数日志
                    System.out.println("成功读取温度数据 - IP: " + ip + 
                        ", 左工位编号: " + leftMachineCode + 
                        ", 右工位编号: " + rightMachineCode + 
                        ", 左上温度: " + leftTopTemp + "°C" + 
                        ", 左下温度: " + leftBottomTemp + "°C" + 
                        ", 右上温度: " + rightTopTemp + "°C" + 
                        ", 右下温度: " + rightBottomTemp + "°C");
                    
                    return temperature;
                } catch (Exception e) {
                    // 记录单个设备读取失败，继续处理其他设备
                    System.err.println("读取设备 " + ip + " 温度数据失败: " + e.getMessage());
                    return null;
                }
            }, modbusTaskExecutor);
            
            futures.add(future);
        }
        
        // 收集所有异步任务的结果
        for (CompletableFuture<Temperature> future : futures) {
            try {
                Temperature temperature = future.get();
                if (temperature != null) {
                    temperatureList.add(temperature);
                    successCount++;
                }
            } catch (InterruptedException | ExecutionException e) {
                System.err.println("获取异步任务结果失败: " + e.getMessage());
            }
        }
        
        // 批量插入到数据库
        if (!temperatureList.isEmpty()) {
            temperatureMapper.insertBatchSomeColumn(temperatureList);
            System.out.println("成功插入 " + temperatureList.size() + " 条温度数据记录。");
        }
        
        System.out.println("温度数据读取任务完成，成功读取 " + successCount + " 台设备。");
    }

    /**
     * 检查IP地址是否可达
     * @param ip IP地址
     * @return 是否可达
     */
    private boolean isIpReachable(String ip) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(ip, 502), 1000); // 502是Modbus TCP默认端口，超时时间1秒
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}